
#region Using Statements

using System;
using System.Collections.Generic;
using System.Data;
using FamilyTreeProject.Framework.Entities;
using FamilyTreeProject.Data.Common;
using FamilyTreeProject.Data.Hydrators;
using FamilyTreeProject.Framework;
using FamilyTreeProject.Data.Repositories;

#endregion

namespace FamilyTreeProject.Data.SubSonic.Repositories
{

    /// <summary>
    /// The IndividualRepository Class represents the Individual Business Layer
    /// Methods in this class call methods in the Data Layer
    /// </summary>
    public class IndividualRepository : IIndividualRepository
    {

        #region Private Static Members

        //private static readonly string INDXREFS_CTXTKEY = "familytree_IndivdualsXRefs";

        #endregion

        #region Private Static Properties

        ///// <summary>
        ///// Gets and sets a collection containing Individuals, that have already been 
        ///// processed during this request
        ///// </summary>
        //private static ObjectCollection<IIndividual> CurrentDataSet
        //{
        //    get
        //    {
        //        ObjectCollection<IIndividual> ret = HttpContext.Current.Items[INDXREFS_CTXTKEY] as ObjectCollection<IIndividual>;
        //        if (ret == null)
        //        {
        //            ret = new ObjectCollection<IIndividual>();
        //            HttpContext.Current.Items[INDXREFS_CTXTKEY] = ret;
        //        }
        //        return ret;
        //    }
        //    set
        //    {
        //        HttpContext.Current.Items[INDXREFS_CTXTKEY] = value;
        //    }
        //}

        #endregion

        #region Private Static Methods

        /// <summary>
        /// Hydrates a new individual from the specified <see cref="IDataReader"/> instance
        /// </summary>
        /// <param name="source">The <see cref="IDataReader"/> to read data from</param>
        /// <returns>An IIndividual</returns>
        private IIndividual Hydrate(IDataReader source)
        {
            //Create Individual
            IIndividual ind = Factory.CreateIndividual();

            //Hydrate the individual
            IndividualHydrator.Hydrate(ind, source);
            //if (!CurrentDataSet.Contains(ind.Id))
            //    CurrentDataSet.Add(ind);

            //Return Individual
            return ind;
        }

        /// <summary>
        /// Hydrates a new individual from the specified <see cref="IDataReader"/> instance
        /// </summary>
        /// <param name="source">The <see cref="IDataReader"/> to read data from</param>
        /// <returns>An IIndividual</returns>
        private IIndividual HydrateIndividual(IDataReader source)
        {
            IIndividual ind = null;
            try
            {
                if (source.Read())
                {
                    //Hydrate the Individual
                    ind = Hydrate(source);
                }
            }
            finally
            {
                DataUtil.CloseDataReader(source);
            }

            return ind;
        }

        /// <summary>
        /// Hydrates a List of Individuals from a DataReader representing the Individuals
        /// </summary>
        /// <param name="source">The Data Reader containing the values to use to fill the Individuals.</param>
        /// <param name="closeReader">A flag that indicates whether the Reader should be closed.</param>
        /// <returns>A List of individuals</returns>
        private List<IIndividual> HydrateList(IDataReader source, bool closeReader)
        {
            List<IIndividual> individuals = new List<IIndividual>();

            try
            {
                while (source.Read())
                {
                    //Hydrate the Individual and add to List
                    individuals.Add(Hydrate(source));
                }
            }
            finally
            {
                if (closeReader)
                    DataUtil.CloseDataReader(source);
            }

            return individuals;
        }

        #endregion

        #region Public Static Methods

        /// <summary>
        /// Gets the children of the individual
        /// </summary>
        /// <param name="parentID">The Id of the Parent Individual</param>
        /// <returns>A List of Individuals</returns>
        public List<IIndividual> GetChildrenByParent(int parentID)
        {
            

            return HydrateList(DataPortal.GetChildrenByParent(parentID), true);
        }

        /// <summary>
        /// Gets the children
        /// </summary>
        /// <param name="fatherID">The Id of the Father Individual</param>
        /// <param name="motherID">The Id of the Mother Individual</param>
        /// <param name="totalRecords">The total number of records</param>
        /// <returns>A List of Individuals</returns>
        public List<IIndividual> GetChildrenByParents(int fatherID, int motherID)
        {
            return HydrateList(DataPortal.GetChildrenByParents(fatherID, motherID), true);
        }

        /// <summary>
        /// Get the specified Individual
        /// </summary>
        /// <param name="individualID">The Id of the Individual to get from the database</param>
        /// <returns>The specified Individual</returns>
        public IIndividual GetIndividual(int individualID)
        {
            IIndividual ind = null;

            ////First check the Dictionary of Individuals to see if the Individual has been
            ////retrieved already
            //if (CurrentDataSet.Contains(individualID))
            //    ind = CurrentDataSet[individualID];
            //else
            ind = HydrateIndividual(DataPortal.GetIndividual(individualID));

            return ind;
        }

        /// <summary>
        /// Gets the spouses of the individual
        /// </summary>
        /// <param name="individualID">The Id of the Individual</param>
        /// <returns>A List of Individuals</returns>
        public List<IIndividual> GetSpouses(int individualID)
        {
            return HydrateList(DataPortal.GetSpouses(individualID), true);
        }

        #endregion

    }
}
